//
// Created by 77873 on 2020/7/16 0016.
//

#include "MineCallJava.h"

MineCallJava::MineCallJava(JavaVM *vm, JNIEnv *env, jobject *obj) {

    this->javaVM = vm;
    this->jniEnv = env;
    this->jobj = *obj;
    this->jobj = env->NewGlobalRef(jobj);


    jclass jlz = jniEnv->GetObjectClass(jobj);
    if (!jlz) {

        if (LOG_DEBUG) {
            LOGE("GetObjectClass is error")
        }
        return;
    }

    jmid_parpared = env->GetMethodID(jlz, "onCallParpared", "()V");
    jmid_load = env->GetMethodID(jlz, "onCallLoad", "(Z)V");
    jmid_timeinfo = env->GetMethodID(jlz, "onCallTimeInfo", "(II)V");
    jmid_error = env->GetMethodID(jlz, "onCallError", "(ILjava/lang/String;)V");
    jmid_complete = env->GetMethodID(jlz, "onCallComplete", "()V");
    jmid_valumedb = env->GetMethodID(jlz, "onCCallValumeDB", "(I)V");
    jmid_pcmtoaac = env->GetMethodID(jlz, "encodecPcmToAAc", "(I[B)V");
    jmid_pcminfo = env->GetMethodID(jlz, "onCallPcmData", "([BI)V");
    jmid_pcmrate = env->GetMethodID(jlz, "onCallPcmRate", "(I)V");
    jmid_renderYuv = env->GetMethodID(jlz, "onCallRenderYuv", "(II[B[B[B)V");
}


MineCallJava::~MineCallJava() {

}

void MineCallJava::onCallParpared(int type) {
    if (LOG_DEBUG) {
        LOGE("MineCallJava::onCallParpared")
    }

    if (type == MAIN_THREAD) {
        //主线程
        jniEnv->CallVoidMethod(jobj, jmid_parpared);

        if (LOG_DEBUG) {
            LOGE("主线程调用")
        }

    } else if (type == CHILD_THREAD) {
        if (LOG_DEBUG) {
            LOGE("子线程调用")
        }
        JNIEnv *current_evn;
        if (javaVM->AttachCurrentThread(&current_evn, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("get child thread jnienv error");
                return;
            }
        };
        current_evn->CallVoidMethod(jobj, jmid_parpared);

        if (LOG_DEBUG) {
            LOGE("CallVoidMethod")
        }
        javaVM->DetachCurrentThread();
    }

}

void MineCallJava::onCallLoad(int type, bool isLoad) {

    if (type == MAIN_THREAD) {
        //主线程
        jniEnv->CallVoidMethod(jobj, jmid_load, isLoad);
    } else if (type == CHILD_THREAD) {
        JNIEnv *current_evn;
        if (javaVM->AttachCurrentThread(&current_evn, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("get child thread jnienv error");
                return;
            }
        };
        current_evn->CallVoidMethod(jobj, jmid_load, isLoad);
        javaVM->DetachCurrentThread();
    }

}

void MineCallJava::onCallTimeInfo(int type, int curr, int total) {

    if (type == MAIN_THREAD) {
        //主线程
        jniEnv->CallVoidMethod(jobj, jmid_timeinfo, curr, total);
    } else if (type == CHILD_THREAD) {
        JNIEnv *current_evn;
        if (javaVM->AttachCurrentThread(&current_evn, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("get child thread jnienv error");
                return;
            }
        };
        current_evn->CallVoidMethod(jobj, jmid_timeinfo, curr, total);
        javaVM->DetachCurrentThread();
    }
}

void MineCallJava::onCallError(int type, int code, char *msg) {

    if (type == MAIN_THREAD) {
        //主线程
        jstring jmsg = jniEnv->NewStringUTF(msg);
        jniEnv->CallVoidMethod(jobj, jmid_error, code, jmsg);
    } else if (type == CHILD_THREAD) {
        JNIEnv *current_evn;
        if (javaVM->AttachCurrentThread(&current_evn, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("get child thread jnienv error");
                return;
            }
        };
        jstring jmsg = current_evn->NewStringUTF(msg);
        current_evn->CallVoidMethod(jobj, jmid_error, code, jmsg);
        javaVM->DetachCurrentThread();
    }
}

void MineCallJava::onComplete(int type) {

    if (type == MAIN_THREAD) {
        jniEnv->CallVoidMethod(jobj, jmid_complete);
    } else {
        JNIEnv *current_evn;
        if (javaVM->AttachCurrentThread(&current_evn, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("get child thread jnienv error");
                return;
            }
        };
        current_evn->CallVoidMethod(jobj, jmid_complete);
        javaVM->DetachCurrentThread();
    }

}

void MineCallJava::onCallValumeDB(int type, int db) {
    if (type == MAIN_THREAD) {
        jniEnv->CallVoidMethod(jobj, jmid_valumedb, db);
    } else {
        JNIEnv *current_evn;
        if (javaVM->AttachCurrentThread(&current_evn, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("get child thread jnienv error");
                return;
            }
        };
        current_evn->CallVoidMethod(jobj, jmid_valumedb, db);
        javaVM->DetachCurrentThread();
    }
}

void MineCallJava::OnCallPcmToAAC(int type, int size, void *buffer) {
    if (type == MAIN_THREAD) {
        jbyteArray jbuffer = jniEnv->NewByteArray(size);
        jniEnv->SetByteArrayRegion(jbuffer, 0, size, static_cast<const jbyte *>(buffer));

        jniEnv->CallVoidMethod(jobj, jmid_pcmtoaac, size, jbuffer);

        jniEnv->DeleteLocalRef(jbuffer);

    } else if (type == CHILD_THREAD) {
        JNIEnv *jniEnv;
        if (javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
            if (LOG_DEBUG) {
                LOGE("call OnCallPcmToAAC worng");
            }
            return;
        }
        jbyteArray jbuffer = jniEnv->NewByteArray(size);
        jniEnv->SetByteArrayRegion(jbuffer, 0, size, static_cast<const jbyte *>(buffer));

        jniEnv->CallVoidMethod(jobj, jmid_pcmtoaac, size, jbuffer);

        jniEnv->DeleteLocalRef(jbuffer);

        javaVM->DetachCurrentThread();
    }
}

void MineCallJava::onPcmCallBack(void *buffer, int size) {

    if (LOG_DEBUG) {
//        LOGE("MineCallJava::onPcmCallBack");
    }

    JNIEnv *jniEnv;
    if (javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
        if (LOG_DEBUG) {
            LOGE("call OnCallPcmToAAC worng");
        }
        return;
    }
    jbyteArray jbuffer = jniEnv->NewByteArray(size);
    jniEnv->SetByteArrayRegion(jbuffer, 0, size, static_cast<const jbyte *>(buffer));

    jniEnv->CallVoidMethod(jobj, jmid_pcminfo, jbuffer, size);

    jniEnv->DeleteLocalRef(jbuffer);
    javaVM->DetachCurrentThread();
}

void MineCallJava::onPcmRateCallBack(int sampleRate) {
    JNIEnv *jniEnv;
    if (javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
        if (LOG_DEBUG) {
            LOGE("call OnCallPcmToAAC worng");
        }
        return;
    }

    jniEnv->CallVoidMethod(jobj, jmid_pcmrate, sampleRate);
    javaVM->DetachCurrentThread();
}

void MineCallJava::onCallRenderYuv(int width, int height, uint8_t *fy, uint8_t *fu, uint8_t *fv) {

    JNIEnv *jniEnv;
    if (javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
        if (LOG_DEBUG) {
            LOGE("call onCallRenderYuv worng");
        }
        return;
    }

    jbyteArray y = jniEnv->NewByteArray(width * height);
    jniEnv->SetByteArrayRegion(y, 0, width * height, reinterpret_cast<const jbyte *>(fy));

    jbyteArray u = jniEnv->NewByteArray(width * height / 4);
    jniEnv->SetByteArrayRegion(u, 0, width * height / 4, reinterpret_cast<const jbyte *>(fu));

    jbyteArray v = jniEnv->NewByteArray(width * height / 4);
    jniEnv->SetByteArrayRegion(v, 0, width * height / 4, reinterpret_cast<const jbyte *>(fv));


    jniEnv->CallVoidMethod(jobj, jmid_renderYuv, width, height, y, u, v);

    jniEnv->DeleteLocalRef(y);
    jniEnv->DeleteLocalRef(u);
    jniEnv->DeleteLocalRef(v);

    javaVM->DetachCurrentThread();
}


